package com.bclz.nio.project;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class TestClient {

    private SocketChannel socketChannel;
    private Selector selector;


    public TestClient(){
        try {
            socketChannel=SocketChannel.open(new InetSocketAddress("127.0.0.1",6667));
            socketChannel.configureBlocking(false);
//            if(!socketChannel.connect(new InetSocketAddress("127.0.0.1",6667))){
//                while (!socketChannel.finishConnect()){
//                    System.out.println("等待连接...");
//                }
//            }
            selector=Selector.open();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void sendMsg(int i){

        try {
            byte[] bytes = "123".getBytes();
            ByteBuffer wrap = ByteBuffer.wrap(bytes);
            socketChannel.write(wrap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void listen(){


        try {
            socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
            while (true){
                try {
                    int select = selector.select(3000);
                    if(select >0){
                        Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                        while(iterator.hasNext()){
                            SelectionKey key=iterator.next();
                            if(key.isReadable()){
                                System.out.println("read...");
                                StringBuilder sb=new StringBuilder();
                                SocketChannel socketChannel = (SocketChannel) key.channel();
                                InetSocketAddress remoteAddress = (InetSocketAddress)socketChannel.getRemoteAddress();
                                try {

                                    ByteBuffer attachment =(ByteBuffer) key.attachment();
                                    System.out.println("读取之前"+attachment.mark());
                                    while(socketChannel.read(attachment)>0){
                                        System.out.println(attachment.mark());
//                                        attachment.flip();
                                        sb.append(new String(attachment.array()));
                                        /**
                                         * 通道数据需要读取干净,必须得clear，
                                         * nio是一种水平触发(操作系统认为数据没读完，会一直通知),
                                         * 下次再有数据进来，read到该ByteBuffer缓冲区,如果缓冲区够大(position位置会一直移动，会有重复数据)，
                                         * 如果缓冲区比较小(比如刚好只够一次),数据read就会=0或者小于1，这个数据就没有成功写到缓冲区，系统就会一直通知selector,select会一直发读事件
                                         * */
                                        attachment.clear();
                                    }
                                    Thread.sleep(1000);
                                    System.out.println(remoteAddress.getHostString()+":"+remoteAddress.getPort()+"  "+sb.toString());
                                }catch (Exception e){
                                    key.cancel();
                                    socketChannel.close();
                                }
                            }
                            iterator.remove();
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (ClosedChannelException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws InterruptedException {

            TestClient client=new TestClient();
            client.sendMsg(Integer.valueOf(String.valueOf(Thread.currentThread().getId())));
            client.listen();

    }
}
